<template>
  <div class="container ivu-p">
    <div class="dialog">
      <template v-for="(item, index) in dialogs" :key="index">
        <div class="dialog-item" :class="{ 'dialog-item-me': item.role === 'me', 'dialog-item-ai': item.role === 'ai' }">
          <div class="dialog-item-main">{{ item.text }}</div>
        </div>
      </template>
    </div>
    <div class="question ivu-mt">
      <Input v-model="question" type="textarea" :autosize="{ minRows: 4, maxRows: 6 }" placeholder="输入内容..." />
      <Row class="ivu-mt">
        <Col>
          <Button type="primary" size="large" icon="md-send" :loading="loading" @click="handleSend">发送</Button>
        </Col>
        <Col>
          <Button size="large" class="ivu-ml" icon="md-add" :disabled="loading" @click="handleNewChat">新对话</Button>
        </Col>
        <Col>
          <Button size="large" class="ivu-ml" icon="md-settings" :disabled="loading" @click="handleOpenPrompt">设置 Prompt</Button>
        </Col>
      </Row>
      <Typography class="ivu-text-center ivu-m">
        Powered By <img src="./assets/logo.png" class="logo"> <a href="https://inscode.net" target="_blank">InsCode.net</a>
      </Typography>
    </div>
    <Modal v-model="showPrompt" title="设置 Prompt" footer-hide :styles="{top: '20px'}">
      <Title :level="4">Prompt：</Title>
      <Input v-model="prompt" type="textarea" :autosize="{minRows: 3,maxRows: 5}" placeholder="例如：写一个策划，主题是_____" />
      <Title class="ivu-mt" :level="4">推荐：</Title>
      <Space :wrap="true">
        <Button @click="handleSetPrompt('写一篇140字以内的朋友圈配文，语言风格要浪漫文艺的，主题是__________')">朋友圈神器</Button>
        <Button @click="handleSetPrompt('扮演一位知心姐姐进行在线聊天。__________')">知心姐姐</Button>
        <Button @click="handleSetPrompt('你现在需要扮演一个高情商、幽默的人，去参加一些聚会社交，请帮我回应接下来的问题，__________')">高情商回复</Button>
        <Button @click="handleSetPrompt('我是你的专属心理咨询师，你有什么想咨询的么？')">心理咨询师</Button>
      </Space>
      <Title class="ivu-mt" :level="4">操作：</Title>
      <Button icon="md-trash" @click="handleClearPrompt">清空 Prompt</Button>
      <Button size="large" type="primary" long class="ivu-mt" @click="handleSavePrompt">保存</Button>
    </Modal>
  </div>
</template>
<script>
import { fetchEventSource } from '@microsoft/fetch-event-source';
import { apiKey, apiUrl } from './api';

let prompt = '';

export default {
  data() {
    return {
      question: '',
      loading: false,
      dialogs: [],
      prompt: '',
      showPrompt: false
    }
  },
  methods: {
    handleSend() {
      if (this.loading || this.question === '') return;
      this.loading = true;

      const question = this.question;
      this.question = '';

      this.dialogs.push({
        id: this.dialogs.length + 1,
        role: 'me',
        text: question
      });

      const aiDialogID = this.dialogs.length + 1;

      this.dialogs.push({
        id: aiDialogID,
        role: 'ai',
        text: 'AI 思考中...'
      });

      const dialog = this.dialogs.find(item => item.id === aiDialogID);

      /**
       * 发送请求，InsCode 已经集成了 GPT 能力
       * 在 vite.config.js 中已通过环境变量写入了 apiKey（该 key 是动态写入使用者的，在 IDE 中是作者，发布到社区是运行该作品的用户）
       * 发布到社区后，将消耗运行者的额度
       * 注意：如果部署应用，任何人通过部署后的域名访问应用时，都将消耗部署者的额度
       */
      const body = {
        messages: [
          {
            role: 'user',
            content: prompt + question
          }
        ],
        apikey: apiKey
      }

      const source = fetchEventSource(apiUrl, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(body),
        onopen: (response) => {
          dialog.text = '';
        },
        onmessage: (msg) => {
          if (msg.data === '[DONE]') {
            this.loading = false;
            return;
          };
          const data = JSON.parse(msg.data);
          const finish_reason = data.choices[0].finish_reason;
          const finish = finish_reason === 'stop' || finish_reason === 'length';
          const content = data.choices[0].delta.content;

          if (finish) {
            this.loading = false;
          } else if (content) {
            const text = content;
            dialog.text += text;
          }
        },
        onerror: (err) => {
          console.log("error", err);
        }
      });
    },
    handleNewChat() {
      this.dialogs = [];
    },
    handleOpenPrompt () {
      this.showPrompt = true;
    },
    handleSetPrompt (prompt) {
      this.prompt = prompt;
    },
    handleSavePrompt () {
      if (!this.prompt) {
        this.$Message.error({
          content: '提示词内容不能为空',
          duration: 3,
          background: true
        });
      } else {
        const prompt = this.prompt;
        localStorage.setItem('setting-prompt', prompt);
        this.showPrompt = false;
        this.handleLoadPrompt();
      }
    },
    handleLoadPrompt () {
      const localPrompt = localStorage.getItem('setting-prompt');
      if (localPrompt) {
        this.prompt = localPrompt;
        prompt = localPrompt;
        this.$nextTick(() => {
          this.$Message.success({
            content: '已加载 Prompt',
            background: true
          });
        });
      }
    },
    handleClearPrompt () {
      localStorage.removeItem('setting-prompt');
      this.prompt = '';
      prompt = '';
      this.$nextTick(() => {
        this.$Message.success({
          content: '已清空 Prompt',
          background: true
        });
      });
    }
  },
  mounted () {
    this.handleLoadPrompt();
  }
}
</script>
<style>
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.dialog {
  flex: 1;
  overflow: auto;
}

.dialog-item {
  display: flex;
}

.dialog-item-main {
  max-width: 80%;
  padding: 8px;
  word-wrap: break-word;
  margin-top: 16px;
  border-radius: 4px;
}

.dialog-item-me {
  justify-content: flex-end;
}

.dialog-item-me .dialog-item-main {
  background-color: antiquewhite;
}

.dialog-item-ai .dialog-item-main {
  background-color: #eee;
}
.logo{
  width: 16px;
  height: 16px;
  vertical-align: middle;
  position: relative;
  top: -1px;
}
</style>